<?php
/**
 * Created by PhpStorm.
 * User: xmy2
 * Date: 18-8-9
 * Time: 下午11:06
 */

namespace vola;

use vola\excetion\ErrorException;

class Error
{
    private static $class;
    public static function init() {
        if (empty(self::$class)) {
            self::$class = new self();
        }
        return self::$class;
    }

    public function __construct()
    {

        if (Container::get('app')->app_debug()) {
            ini_set('display_errors', 'on');
            error_reporting(E_ALL&~E_NOTICE&~E_WARNING);
            set_error_handler([$this,'error'], E_ERROR);
            set_exception_handler([$this,'exception']);
        }

        register_shutdown_function([$this,'shutdown']);
    }

    public function exception($e) {

        Container::get('app')->log('exception',  get_class($e) . '   ' . $e->getMessage() . "\n" . $e->getTraceAsString(), 'error');
        Container::get('response')->http_response_code(500);
        // var_dump($_ENV);
        if (Container::get('app')->app_debug() && Container::get('app')->app_error() ) {
            $this->output($e); // 这里显示 所有的异常都最终指向这个方法
        }
    }

    /**
     * @param $erron 错误码
     * @param $errstr 错误信息
     * @param $errfile 错误所在文件
     * @param $errline 错误在文件的哪一行
     * @throws ErrorException
     */
    public function error($erron, $errstr, $errfile, $errline) {
        $exception = new exception\ErrorException($errstr, $erron, $errfile, $errline);
        if (error_reporting() & $erron) {
            throw $exception;
        }
        $this->exception($exception);
    }

    public function shutdown() {
        if (!is_null($error = error_get_last()) && $this->isFatal($error['type'])) {
            $exception = new exception\FatalException($error['message'], $error['type'], $error['file'], $error['line']);
            throw $exception;
        }
        // print_r($error);
        Container::get('app')->endapp();
    }

    private function isFatal($type)
    {
        // 判断是不是致命错误 致命错误会提前终止程序,但是会调用shutdown
        return in_array($type, [E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_PARSE]);
    }

    /**
     * @param Exception|\exception\FatalException|RuntimeException|mixed $e
     */
    private function output($e) {

//        echo '<pre>' . (var_export($e, true)) . '</pre>';
        include 'exception/tpl.php';
    }

    public static function the($name, $message = '') {
        $class = "\\vola\\exception\\{$name}Exception";
        throw new $class($message);
    }
}